package ewu

import gui.Layout
import scala.collection.mutable.ArrayBuffer
import ewu._
import lang.LOC
import scala.swing._
import scala.swing.Dialog._

/**
 * Die Klasse Schleife stellt Schleifenkonstrukte dar.
 * Zu einer Schleife gehoeren eine auszuwertende Boolexpression "bedingung"
 * sowie eine Anweisungsfolge die solange ausgefuehrt wird, wie die bedingung
 * true ergibt. 
 */

case class Schleife (bedingung: BoolExpression, doTeil: Anweisungsfolge) extends Anweisung {
  
  var bnd: Bound = null
  var tmpBnd: BigInt = null
  
  override def setBound(tmpBnd: Bound) = {
    bnd = tmpBnd
  }
  
  def isBound(): Boolean = {
    return !(bnd == null)
  }

  def getBound(env: Environment, aenvironment: ArrayEnvironment): (String, Boolean) = {
    var (ausgabe, bed) = bnd.traceB(env, aenvironment, tmpBnd)
    tmpBnd = bnd.getValue(env, aenvironment)
    return (ausgabe, bed)
  }

  override def numerate(num: List[Int]) = {
    number = num
    doTeil.numerate(1 :: num)
  }
  
  override def tabbate(i: Int) = {
    tabs = i
    doTeil.tabbate(i+1)
  }

  override def toString(): String = {
    var ausgabe: String = HM.numberString(number)
    ausgabe ++= "WHILE (" ++ bedingung.toString ++ ") LOOP\n"
    ausgabe ++= doTeil.toString
    ausgabe ++= HM.numberString(number) ++ "END LOOP;\n"
    return ausgabe
  }
  
  override def toTabString: String = {
    var ausgabe: String = HM.tabString(tabs)
    ausgabe ++= "WHILE (" ++ bedingung.toString ++ ") LOOP\n"
    ausgabe ++= doTeil.toTabString
    ausgabe ++= HM.tabString(tabs) ++ "END LOOP;\n"
    return ausgabe
  }


  override def trace(env: Environment, aenvironment: ArrayEnvironment, tt: Layout, h: Int):
                                                                    (String, Boolean, Int) = {
    var ausgabe: String = ""
    var contH = true
    var countH = h

    while(bedingung.evaluate(env) == Some(true) && contH) {
      if(isBound) {
        var (tmpAusgabe, bed) = getBound(env, aenvironment)
        ausgabe ++= tmpAusgabe
        if(!bed) {
          var r: Result.Value = null
          r = Dialog.showConfirmation(tt, LOC.get("AuswertungFalse")+ "\n" + tmpAusgabe,
                                      LOC.get("Fehler"), Dialog.Options.YesNo,
                                      Dialog.Message.Question)
          if(r.equals(Result.No)) {
            return (ausgabe, false, countH+1)
          }
        }
      }
      
      ausgabe ++= (HM.numberString(number) ++ "WHILE (" ++ bedingung.toString ++ ") LOOP => ")
      if(bedingung.evaluate(env) == Some(true)) {
        ausgabe ++= "true\n" //++ env.toString ++ "\n"
        var (tmpAusgabe, cont, count) = doTeil.trace(countH+1, env, tt)
        contH = cont
        countH = count
        ausgabe ++= tmpAusgabe
      }
    }
    
//    if(isBound && contH) {
//      var (tmpAusgabe, bed) = getBound(env, aenvironment)
//      ausgabe ++= tmpAusgabe
//      if(!bed) {
//        var r: Result.Value = null
//        r = Dialog.showConfirmation(tt, LOC.get("AuswertungFalse")+ "\n" + tmpAusgabe,
//                                    LOC.get("Fehler"), Dialog.Options.YesNo,
//                                    Dialog.Message.Question)
//        if(r.equals(Result.No)) {
//          return (ausgabe, false, countH+1)
//        }
//      }
//      tmpBnd = null
//    }
    ausgabe ++= (HM.numberString(number) ++ "WHILE (" ++ bedingung.toString
            ++ ") LOOP => false\n")

    return (ausgabe, contH, countH+1)
  }

  override def propagate(assI: Anweisung): Anweisungsfolge = {
    var tmp: ArrayBuffer[Anweisung] = ArrayBuffer()
    assI match {
      case Assertion (_: String, expr: BoolExpression) =>
        var ass = Assertion("", AND(expr, bedingung).reduce)
        ass.tabbate(tabs+1)
        doTeil.addAnweisung(ass, 0)
        ass = Assertion("", expr.reduce)
        ass.tabbate(tabs+1)
        doTeil.addAnweisung(ass, doTeil.getLaenge)
        doTeil.propagate
        tmp.append(this)
        ass = Assertion("", AND(expr, Not(bedingung).reduce))
        ass.tabbate(tabs)
        tmp.append(ass)
      case _ =>
        null
    }
    Anweisungsfolge(tmp)
  }

  override def propagate(assV: Anweisung,
                         assN: Anweisung): Anweisungsfolge = null
                         
  def getVariables(a: ArrayBuffer[Name]) = {
    bedingung.getVariables(a)
    var a1 = doTeil.getVariables()
    
    for(i <- 0 to a1.length-1) {
      if(!a.contains(a1(i)))
        a.append(a1(i))
    }
  }
  
  def replaceVariable(fromVar: Name, toVar: Expression) : Unit = {
    bedingung.replaceVariable(fromVar, toVar)
    var a1 = doTeil.replaceVariable(fromVar, toVar)
  }

}


 